import { Ref } from 'vue'
import { Viewer } from '../../../types'
import HotkeyRegister, { HotkeyHandlerParams } from './HotkeyRegister'
import useHotkey from './useHotkey'
import useZoom from './useZoom'
import useWidgetMove from './useWidgetMove'
import useWidgetCopy from './useWidgetCopy'
import useWidgetOperate from './useWidgetOperate'

/** 检测注册按键是否匹配当前按键  */
function isKeyMatched(key: string, registerKeys?: string | string[]) {
  if (!key || !registerKeys) return false

  /** 转小写对比 */
  key = key.toLowerCase()

  if (typeof registerKeys === 'string') {
    registerKeys = registerKeys.toLowerCase()
  } else {
    registerKeys = registerKeys.map(key => key.toLowerCase())
  }

  return registerKeys === key || (Array.isArray(registerKeys) && registerKeys.includes(key))
}

/** 快捷键操作 */
export default function useHotkeys(
  viewer: Viewer,
  viewerEl: Ref<HTMLElement | null>,
  emit: (key: 'hotkey', ...rest: any) => void
) {
  /** 注册的按键操作 */
  const register = new HotkeyRegister()

  /** 快捷键 */
  useHotkey(params => {
    const { e, type } = params
    const { key, code, ctrlKey, metaKey } = e

    // 文档查看区域未激活则不执行快捷键
    if (!viewer.state.activated) return

    /** 当前时间戳 */
    const now = new Date().getTime()

    /** 匹配的已注册快捷键 */
    const matched = register.list.filter(
      item =>
        // 按键类型匹配
        (!item.type || item.type === type) &&
        // 按键匹配
        (isKeyMatched(key, item.keys) || isKeyMatched(code, item.codes)) &&
        // Ctrl 或 Cmd 按键
        (item.ctrlOrCmd ? ctrlKey || metaKey : true)
    )

    const actionParams: HotkeyHandlerParams = { ...params, viewer }

    // 执行快捷键操作
    const handlerResults = matched.map(item => {
      if (item.interval && now - (item.lastTime || 0) < item.interval) return e.preventDefault()

      item.lastTime = now

      return item.handler(actionParams)
    })

    emit('hotkey', actionParams)

    if (handlerResults.some(item => item === false)) return false
  })

  /** 缩放 */
  useZoom(register, viewer, viewerEl)

  /** 控件移动 */
  useWidgetMove(register)

  /** 控件复制 */
  useWidgetCopy(register)

  /** 控件操作 */
  useWidgetOperate(register)
}
